package com.hyl.icon.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hyl.icon.common.ErrorCode;
import com.hyl.icon.exception.BusinessException;
import com.hyl.icon.model.entity.Template;
import com.hyl.icon.service.IconService;
import com.hyl.icon.service.TemplateService;
import com.hyl.icon.utils.ExecuteUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Queue;

@Service
@Slf4j
public class IconServiceImpl implements IconService {

    @Resource
    private TemplateService templateService;

    @Override
    public BufferedImage getTemplateResult(MultipartFile backgroundFile, MultipartFile logoFile, String brandName, String phone, String address) {
        QueryWrapper<Template> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",1899320693348249601L);

        Template template = templateService.getOne(queryWrapper);
        if (template != null) {
           try {
               // 2. 编译并执行代码
               String code = template.getCode();
               BufferedImage result = ExecuteUtils.compileAndRun(code, backgroundFile, logoFile, brandName, phone, address);
               return result;
           }catch (Exception e){
               throw new BusinessException(ErrorCode.PARAMS_ERROR, "模板编译失败");
           }
        }

        return null;
    }




    /**
     * 绘制两个字或者三个字的竖排
     * @param backgroundFile
     * @param logoFile
     * @param brandName
     * @param phone
     * @param address
     * @return
     */
    @Override
    public BufferedImage generateBrandImage(MultipartFile backgroundFile, MultipartFile logoFile, String brandName, String phone, String address) {
        //TODO根据logo名的多少去数据库查询对应的模板
        try {
            // 目标图像尺寸
            int width = 992;
            int height = 3622;
            // 读取背景图
            BufferedImage background = ImageIO.read(backgroundFile.getInputStream());
            BufferedImage logo = ImageIO.read(logoFile.getInputStream());
            // 创建目标图像
            BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = result.createGraphics();

            // 开启抗锯齿
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            // 绘制背景
            g.drawImage(background, 0, 0, width, height, null);

            // 计算安全区域 (避免占用背景的底部 1/3)
            int safeHeight = (int) (height * 2.0 / 3);
            int margin = 150; // 增加 logo 到顶部的距离

            // 计算 Logo 位置 (缩小至背景宽度的 2/3 和背景高度的 1/5)
            int logoMaxWidth = width / 2 ;  // 将 logo 宽度设置为背景宽度的 1/2
            int logoMaxHeight = safeHeight / 5;
            int logoWidth = Math.min(logoMaxWidth, logo.getWidth());
            int logoHeight = Math.min(logoMaxHeight, logo.getHeight());
            int logoX = (width - logoWidth) / 2;
            int logoY = margin;
            g.drawImage(logo, logoX, logoY, logoWidth, logoHeight, null);

            // 设定字体
            // 设定品牌名称字体
            g.setFont(new Font("SansSerif", Font.BOLD, 400));
            g.setColor(Color.BLACK);
            FontMetrics brandMetrics = g.getFontMetrics();

            // 计算品牌名称整体高度
            int fontSize = 400;
            int textX = (width - fontSize) / 2;

            // 计算品牌名称起始 Y 位置，确保整体居中
            int brandY = logoY +  logoHeight + fontSize;
            // 竖排绘制品牌名称
            for (char c : brandName.toCharArray()) {
                g.drawString(String.valueOf(c), textX, brandY);
                brandY += fontSize;  // 每个字的间距等于字体大小
            }

            // 手机电话
            g.setFont(new Font("SansSerif", Font.BOLD, 50));

            int phoneY = 1982;
            System.out.println("phoneY"+phoneY);
            drawCenteredString(g, phone, width, phoneY);

            // 地址
            int addressY = phoneY + 100;
            drawCenteredString(g, address, width, addressY);

            g.dispose();
            return result;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 居中绘制字符串
    private void drawCenteredString(Graphics2D g, String text, int width, int y) {
        FontMetrics metrics = g.getFontMetrics();
        int x = (width - metrics.stringWidth(text)) / 2;
        g.drawString(text, x, y);
    }

    /**
     * 生成品牌 Logo 图片(测试v0)
     *
     * @param backgroundFile 背景图片 MultipartFile
     * @param logoFile       Logo 图片 MultipartFile
     * @param brandName      品牌名称
     */
    @Override
    public BufferedImage generateBrandImage(MultipartFile backgroundFile, MultipartFile logoFile, String brandName) {
        try {
            // 读取背景图片
            BufferedImage background = this.convertMultipartFileToBufferedImage(backgroundFile);
            int width = background.getWidth();
            int height = background.getHeight();

            // 创建新图像
            BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = outputImage.createGraphics();

            // 开启抗锯齿
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // 画背景图
            g2d.drawImage(background, 0, 0, null);

            // 计算 Logo 尺寸（占背景高度的 1/5）
            int logoHeight = height / 10;
            int logoWidth = logoHeight;  // 假设 Logo 为正方形

            // 计算 Logo 位置（靠近顶部）
            int logoX = (width - logoWidth) / 2;
            int logoY = height / 20;  // 让 Logo 更靠顶部

            // 读取 Logo 图片并缩放
            BufferedImage logo = convertMultipartFileToBufferedImage(logoFile);
            BufferedImage resizedLogo = resizeImage(logo, logoWidth, logoHeight);
            g2d.drawImage(resizedLogo, logoX, logoY, null);

            // 计算品牌名称区域高度（占背景高度的 1/3）
            int brandHeight = height / 3;
            int numChars = brandName.length();
            int fontSize = brandHeight / numChars;  // 计算字体大小，使整体高度固定

            // 限制最小字体大小，防止过小
            fontSize = Math.max(fontSize, height / 20);

            // 设定字体
            g2d.setFont(new Font("SansSerif", Font.BOLD, fontSize));
            g2d.setColor(Color.white);

            // 计算品牌名和 Logo 之间的间距（增大间距，防止接触）
            int spaceBetween = fontSize;
            int textStartY = logoY + logoHeight + spaceBetween;
            int textX = (width - fontSize) / 2;

            // 竖排绘制品牌名称
            for (char c : brandName.toCharArray()) {
                g2d.drawString(String.valueOf(c), textX, textStartY);
                textStartY += fontSize;  // 每个字的间距等于字体大小
            }

            // 释放资源
            g2d.dispose();

            return outputImage;

        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"生成品牌 Logo 图片失败");
        }
    }


    /**
     * 将 MultipartFile 转换为 BufferedImage
     */
    private BufferedImage convertMultipartFileToBufferedImage(MultipartFile file) throws IOException {
        byte[] bytes = file.getBytes();
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        return ImageIO.read(bais);
    }

    /**
     * 缩放图片
     */
    private BufferedImage resizeImage(BufferedImage originalImage, int width, int height) {
        BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = resizedImage.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.drawImage(originalImage, 0, 0, width, height, null);
        g2d.dispose();
        return resizedImage;
    }

    /**
     * 将 BufferedImage 转换为 Base64 字符串
     */
    @Override
    public String imageToBase64(BufferedImage image, String format){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, format, baos);
            baos.flush();
            baos.close();
            byte[] imageBytes = baos.toByteArray();
            return Base64.getEncoder().encodeToString(imageBytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
